package cn.schoolwow.quickdao.module.database.dml.instance.flow.delete.common;

import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickdao.module.database.dml.common.domain.GetBatchParametersSupplier;
import cn.schoolwow.quickdao.module.database.dml.common.domain.ManipulationOption;
import cn.schoolwow.quickdao.module.database.parent.domain.GetStatementSupplier;
import cn.schoolwow.quickdao.module.database.parent.flow.GetAndCacheStatementFlow;
import cn.schoolwow.quickdao.module.database.parent.flow.executor.ExecuteBatchUpdateConnectionFlow;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instance.QueryInstance;

import java.util.ArrayList;
import java.util.List;

public class DeleteByMultipleUniqueKeyFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setStatement(flowContext);
        executeStatement(flowContext);
    }

    @Override
    public String name() {
        return "根据多个唯一约束字段删除实例";
    }

    private void setStatement(FlowContext flowContext) {
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        Entity entity = (Entity) flowContext.checkData("entity");

        GetStatementSupplier getStatementSupplier = new GetStatementSupplier() {
            @Override
            public String getStatement() {
                StringBuilder sqlBuilder = new StringBuilder();
                sqlBuilder.append("delete from " + quickDAOConfig.databaseContext.databaseProvider.escape(entity.tableName) + " where ");
                for(Property uniqueKeyProperty:entity.uniqueProperties){
                    sqlBuilder.append(quickDAOConfig.databaseContext.databaseProvider.escape(uniqueKeyProperty.column) + " = ? and ");
                }
                sqlBuilder.delete(sqlBuilder.length() - 5, sqlBuilder.length());
                return sqlBuilder.toString();
            }
        };

        flowContext.startFlow(new GetAndCacheStatementFlow())
                .putReturnData("sqlCacheName", "deleteByMultipleUniqueKey_"+entity.tableName)
                .putInstanceData(getStatementSupplier, GetStatementSupplier.class)
                .execute();
    }

    private void executeStatement(FlowContext flowContext) {
        ManipulationOption manipulationOption = flowContext.checkInstanceData(ManipulationOption.class);
        Object[] instances = flowContext.containKey("instances")?
                flowContext.checkData("instances", Object[].class)
                :new Object[]{flowContext.checkData("instance")};

        flowContext.startFlow(new ExecuteBatchUpdateConnectionFlow())
                .putTemporaryData("perBatchCount", manipulationOption.perBatchCount)
                .putTemporaryData("name", "批处理根据唯一约束字段删除实例数组")
                .putTemporaryData("size", instances.length)
                .putTemporaryData("getBatchParametersSupplier",new GetBatchParametersSupplier() {
                    @Override
                    public List<Object> getBatchParameters(Integer index) throws Exception {
                        flowContext.putTemporaryData("instance", instances[index]);
                        setParameters(flowContext);
                        List<Object> parameters = (List<Object>) flowContext.checkData("parameters");
                        return parameters;
                    }
                })
                .execute();
    }

    private void setParameters(FlowContext flowContext) {
        Entity entity = flowContext.checkData("entity", Entity.class);
        Object instance = flowContext.checkData("instance");

        List<Object> parameters = new ArrayList();
        for(Property uniqueProperty:entity.uniqueProperties){
            Object value = QueryInstance.newQuery(instance)
                    .execute()
                    .getSingleFieldValue(uniqueProperty.name);
            if(null==value){
                throw new IllegalArgumentException("唯一约束字段不能为空!实体类:"+entity.clazz.getName()+",字段名:"+uniqueProperty.name);
            }
            parameters.add(value);
        }
        flowContext.putTemporaryData("parameters", parameters);
    }
}
